/*
 *	Perlin Production Co. Ltd. September 2012 (c).
 *			ClrSpc.c
 *		
 */

#include "stdio.h"
#include "paramlib.h"
#include "WinGDI.h"

#define _DEBUG 0
 
#define	CLRFMT	"%03u: [b:%03u, g:%03u, r:%03u]\n" 


/* COLORSPACE EXPANSION */

RGB* CSEBW(_rgb, _index)
RGB*		_rgb;		/* Vector Color Space components */
unsigned	_index;		/* Index in color space 0-0xFF */
{
	InitRGB(_rgb,_index,_index,_index);
	_rgb->rgbReserved = _index;
	return _rgb;
}



/* Color expansion from 233 colorspace to components 888 */

RGB* CSELin(_rgb, _index)
RGB*		_rgb;		/* Vector Color Space components */
unsigned	_index;		/* Index in color space 0-0xFF */
{
#if _DEBUG
	char	text[0x100];
#endif	
	
	if (!_index) InitRGB(_rgb,0,0,0);			/* lo */
	else if (_index >= 0xFF) InitRGB(_rgb,0xFF,0xFF,0xFF);	/* hi */
	else
	{
		_rgb->rgbBlue = (_index >> 6) & 0x3;
		if (_rgb->rgbBlue)
		{
			_rgb->rgbBlue *= 64;
		}
		
		_rgb->rgbGreen	= (_index >> 3) & 0x7;
		if (_rgb->rgbGreen)
		{
			_rgb->rgbGreen = 32 * (_rgb->rgbGreen+1);
			if (!_rgb->rgbGreen) --_rgb->rgbGreen;
			
		}
	
		_rgb->rgbRed	= (_index ) & 0x7;
		if (_rgb->rgbRed)
		{
			_rgb->rgbRed = 32 * (_rgb->rgbRed+1);
			if (!_rgb->rgbRed) --_rgb->rgbRed;
		}
	}	
#if _DEBUG
	sprintf(text, "Index %3x:", _index);
	PutRGB(_rgb,text);
	while (ki() != 0xd) {}
#endif	
	
	_rgb->rgbReserved = _index;
	return _rgb;
}



/* Scale individual colors in 888 color space */
		
RGB* CSNLin(_rgb, _rgbMax)
RGB*		_rgb;		/* Vector Color Space components */
RGB*		_rgbMax;	/* Maximum component values */
{
	if (_rgbMax->rgbBlue != 0xFF)
		_rgb->rgbBlue  = (_rgbMax->rgbBlue  * _rgb->rgbBlue )  / 0xFF;
		
	if (_rgbMax->rgbGreen != 0xFF)
		_rgb->rgbGreen = (_rgbMax->rgbGreen * _rgb->rgbGreen ) / 0xFF;
		
	if (_rgbMax->rgbRed != 0xFF)
		_rgb->rgbRed   = (_rgbMax->rgbRed   * _rgb->rgbRed  )  / 0xFF;
	
	return _rgb;
}



	
CLR_Gen(_rgb, _rgbMax, _expand, _scale, _verbose)
RGB	*_rgb;			/* destination RGB[0x100] array */ 
RGB	*_rgbMax;		/* maximum RGB for scaling */
RGB*	(*_expand)();		/* pointer to color space conversion function */
RGB*	(*_scale)();		/* pointer to scaling function */
int	_verbose;
{
	unsigned	index;
	RGB		*rgb;
	int		r,g,b;
	int		gain;
	char		text[0x100];
	
	if (_verbose) printf("Generating colorspace component levels\n");
	
	setmem(_rgb,sizeof(_RGB)*0x100,0);
	
	gain = _rgbMax->rgbReserved - 127;
	
	for	( index=0, rgb = _rgb
		; index < 0x100
		; ++index, ++rgb
		)
	{
		(*_expand)(rgb, index);
		(*_scale) (rgb, _rgbMax);
		if (gain) AddRGB(rgb, gain);
	}
}



RGB*	CLR_Rd(_rgb, _fname, _verbose)
RGB*	_rgb;
char*	_fname;
int	_verbose;
{
	FILE	*fd;
	RGB	*result;
	int	i,idxClr;
	
	result = 0;
	
	if (fd = fopen(_fname,"r",128))
	{
		if (_verbose) printf("Reading %s component levels\n", _fname);
		
		result = _rgb;
		for (i=0; i < 0x100; ++i, ++_rgb)
		{
			fscanf( fd, CLRFMT
				, &idxClr
				, &(_rgb->rgbBlue)
				, &(_rgb->rgbGreen)
				, &(_rgb->rgbRed)
				);
			_rgb->rgbReserved = 0; /* color not reserved */
			/*
			{
				result = 0;
				trouble("Read error in", _fname);
			}
			*/
		}
		if (fclose(fd)) perror(_fname);
		
	}
	else
	{
	 if (_verbose) printf("Failed opening colorspace level file %s\n", _fname);
	}
	return result;
}




RGB*	CLR_Wr(_rgb, _fname, _verbose)
RGB	*_rgb;
char	*_fname;
int	_verbose;
{
	FILE	*fd;
	RGB	*result;
	int	i;
	
	result = 0;
	 
	if (fd = fopen(_fname,"w",128))
	{
		if (_verbose == VERBMAX) printf("Saving colorspace levels to %s\n", _fname);
		
		result = _rgb;
		
		for (i=0; i < 0x100; ++i, ++_rgb)
		{
			fprintf	( fd, CLRFMT
				, i			
				, _rgb->rgbBlue
				, _rgb->rgbGreen
				, _rgb->rgbRed
				);
			if ((_verbose == VERBMAX) && (!(i & 7))) putchar('.');
		}
		if (_verbose == VERBMAX) putchar('\n');
					
			
		if (fclose(fd)) perror(_fname);
		else if (_verbose) printf("Colorspace component levels saved to %s\n", _fname);
	}
	else trouble("create colorspace level file", _fname);
	return result;
}
